import axios, { AxiosInstance, AxiosError } from 'axios'
import { getEnvironmentConfig } from './apiConfig'
import { apiCache, CacheKeyGenerator } from '@/utils/apiCache'
import { ApiClientError } from './apiError'
import { errorHandler, ErrorType, ErrorSeverity } from './errorHandler'
import { withApiRetry } from './retryMechanism'

import {
    Dataset,
    CreateDatasetRequest,
    UpdateDatasetRequest,
    DatasetStats
} from '@/types/dataset'
import { type ImageData as CustomImageData, ImageMetadata } from '@/types/image'
import {
    Task,
    TaskResult,
    TaskStatusInfo,
    TaskParams,
    CreateTaskRequest,
    UpdateTaskRequest
} from '@/types/task'
import {
    ApiResponse,
    ApiError,
    ApiClient as IApiClient,
    ApiEndpoints,
    PaginatedResponse
} from '@/types/api'
import { PaginationOption } from '@/types/common'

// 创建 Axios 实例
const createApiClient = (): AxiosInstance => {
    const config = getEnvironmentConfig()

    const client = axios.create({
        baseURL: config.BASE_URL,
        timeout: config.TIMEOUT,
        headers: {
            'Content-Type': 'application/json',
        },
    })

    // 请求拦截器
    client.interceptors.request.use(
        (config) => {
            // 添加认证token
            const token = localStorage.getItem('auth_token')
            if (token) {
                config.headers.Authorization = `Bearer ${token}`
            }

            // 添加请求ID用于追踪
            config.headers['X-Request-ID'] = generateRequestId()

            // 开发环境日志
            const envConfig = getEnvironmentConfig()
            if (envConfig.ENABLE_REQUEST_LOGGING) {
                console.log('API Request:', {
                    method: config.method?.toUpperCase(),
                    url: config.url,
                    params: config.params,
                    data: config.data
                })
            }

            return config
        },
        (error) => {
            console.error('Request interceptor error:', error)
            return Promise.reject(error)
        }
    )

    // 响应拦截器
    client.interceptors.response.use(
        (response) => {
            // 开发环境日志
            const envConfig = getEnvironmentConfig()
            if (envConfig.ENABLE_RESPONSE_LOGGING) {
                console.log('API Response:', {
                    status: response.status,
                    url: response.config.url,
                    data: response.data
                })
            }

            return response
        },
        (error: AxiosError) => {
            const apiError = handleApiError(error)

            // 开发环境详细错误日志
            if (process.env.NODE_ENV === 'development') {
                console.error('API Error:', {
                    status: error.response?.status,
                    url: error.config?.url,
                    message: apiError.message,
                    details: apiError.details
                })
            }

            return Promise.reject(apiError)
        }
    )

    return client
}

// 生成请求ID
const generateRequestId = (): string => {
    return `req_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`
}

// 错误处理函数
const handleApiError = (error: AxiosError): ApiClientError => {
    let apiError: ApiClientError

    if (error.response) {
        // 服务器响应错误
        const { status, data } = error.response
        const errorData = data as ApiError

        apiError = new ApiClientError(
            errorData?.message || `HTTP ${status} Error`,
            errorData?.code || `HTTP_${status}`,
            { status, responseData: errorData }
        )
        apiError.status = status

        // 使用错误处理器记录
        errorHandler.handleError(apiError, {
            type: status >= 500 ? ErrorType.NETWORK_ERROR : ErrorType.VALIDATION_ERROR,
            severity: status >= 500 ? ErrorSeverity.HIGH : ErrorSeverity.MEDIUM,
            context: {
                url: error.config?.url,
                method: error.config?.method,
                status,
                responseData: errorData
            },
            showNotification: false // API错误通常由调用方处理通知
        })
    } else if (error.request) {
        // 网络错误
        apiError = new ApiClientError(
            'Network error - please check your connection',
            'NETWORK_ERROR'
        )

        errorHandler.handleError(apiError, {
            type: ErrorType.NETWORK_ERROR,
            severity: ErrorSeverity.HIGH,
            context: {
                url: error.config?.url,
                method: error.config?.method,
                timeout: error.config?.timeout
            },
            showNotification: false
        })
    } else {
        // 其他错误
        apiError = new ApiClientError(
            error.message || 'Unknown error occurred',
            'UNKNOWN_ERROR'
        )

        errorHandler.handleError(apiError, {
            type: ErrorType.UNKNOWN_ERROR,
            severity: ErrorSeverity.MEDIUM,
            context: {
                url: error.config?.url,
                method: error.config?.method
            },
            showNotification: false
        })
    }

    return apiError
}

const apiClient = createApiClient()

// API端点定义
const API_ENDPOINTS: ApiEndpoints = {
    DATASETS: '/datasets',
    DATASET: (id: string) => `/datasets/${id}`,
    IMAGE_DATA: (id: string) => `/images/${id}/data`,
    IMAGE_METADATA: (id: string) => `/images/${id}/metadata`,
    TASKS: (datasetId: string) => `/datasets/${datasetId}/tasks`,
    START_TASK: '/tasks/start',
    TASK_STATUS: (id: string) => `/tasks/${id}/status`,
    TASK_RESULTS: (id: string) => `/tasks/${id}/results`
}

// 辅助函数：构建查询参数
const buildQueryParams = (pagination?: PaginationOption): Record<string, unknown> => {
    if (!pagination) return {}

    const params: Record<string, unknown> = {
        page: pagination.page,
        pageSize: pagination.pageSize
    }

    if (pagination.sort && pagination.sort.length > 0) {
        params.sort = pagination.sort.map(s => `${s.field}:${s.direction}`).join(',')
    }

    if (pagination.filters && pagination.filters.length > 0) {
        pagination.filters.forEach((filter, index) => {
            params[`filter[${index}][field]`] = filter.field
            params[`filter[${index}][operator]`] = filter.operator
            params[`filter[${index}][value]`] = filter.value
        })
    }

    return params
}

// 辅助函数：处理API响应
const handleApiResponse = <T>(response: { data: ApiResponse<T> }): T => {
    if (!response.data.success) {
        throw new ApiClientError(
            response.data.message || 'API request failed',
            response.data.error || 'API_ERROR'
        )
    }
    return response.data.data as T
}

// 扩展的API客户端接口
export interface ExtendedApiClient extends IApiClient {
    // 数据集扩展方法
    createDataset(data: CreateDatasetRequest): Promise<Dataset>
    updateDataset(id: string, data: UpdateDatasetRequest): Promise<Dataset>
    deleteDataset(id: string): Promise<void>
    getDatasetStats(id: string): Promise<DatasetStats>
    getDatasetsWithPagination(pagination?: PaginationOption): Promise<PaginatedResponse<Dataset>>

    // 任务扩展方法
    createTask(data: CreateTaskRequest): Promise<Task>
    updateTask(id: string, data: UpdateTaskRequest): Promise<Task>
    deleteTask(id: string): Promise<void>
    cancelTask(id: string): Promise<void>
    getTasksWithPagination(datasetId: string, pagination?: PaginationOption): Promise<PaginatedResponse<Task>>

    // 批量操作
    uploadImages(datasetId: string, files: File[]): Promise<CustomImageData[]>
    deleteImages(imageIds: string[]): Promise<void>

    // 健康检查
    healthCheck(): Promise<{ status: string; timestamp: string }>
}

// API客户端实现
export const api: ExtendedApiClient = {
    // 数据集相关 - 使用缓存策略
    async getDatasets(): Promise<Dataset[]> {
        return apiCache.cacheApiCall(
            'datasets',
            'all_datasets',
            async () => {
                return withApiRetry(async () => {
                    try {
                        const response = await apiClient.get(API_ENDPOINTS.DATASETS)
                        return handleApiResponse<Dataset[]>(response)
                    } catch (error) {
                        throw error instanceof ApiClientError ? error : new ApiClientError(
                            'Failed to fetch datasets',
                            'FETCH_DATASETS_ERROR'
                        )
                    }
                })
            }
        )
    },

    async getDataset(id: string): Promise<Dataset> {
        return apiCache.cacheApiCall(
            'datasets',
            CacheKeyGenerator.forDataset(id),
            async () => {
                return withApiRetry(async () => {
                    try {
                        const response = await apiClient.get(API_ENDPOINTS.DATASET(id))
                        return handleApiResponse<Dataset>(response)
                    } catch (error) {
                        throw error instanceof ApiClientError ? error : new ApiClientError(
                            `Failed to fetch dataset ${id}`,
                            'FETCH_DATASET_ERROR'
                        )
                    }
                })
            }
        )
    },

    async createDataset(data: CreateDatasetRequest): Promise<Dataset> {
        try {
            const response = await apiClient.post(API_ENDPOINTS.DATASETS, data)
            return handleApiResponse<Dataset>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                'Failed to create dataset',
                'CREATE_DATASET_ERROR'
            )
        }
    },

    async updateDataset(id: string, data: UpdateDatasetRequest): Promise<Dataset> {
        try {
            const response = await apiClient.put(API_ENDPOINTS.DATASET(id), data)
            return handleApiResponse<Dataset>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                `Failed to update dataset ${id}`,
                'UPDATE_DATASET_ERROR'
            )
        }
    },

    async deleteDataset(id: string): Promise<void> {
        try {
            await apiClient.delete(API_ENDPOINTS.DATASET(id))
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                `Failed to delete dataset ${id}`,
                'DELETE_DATASET_ERROR'
            )
        }
    },

    async getDatasetStats(id: string): Promise<DatasetStats> {
        try {
            const response = await apiClient.get(`${API_ENDPOINTS.DATASET(id)}/stats`)
            return handleApiResponse<DatasetStats>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                `Failed to fetch dataset stats for ${id}`,
                'FETCH_DATASET_STATS_ERROR'
            )
        }
    },

    async getDatasetsWithPagination(pagination?: PaginationOption): Promise<PaginatedResponse<Dataset>> {
        try {
            const params = buildQueryParams(pagination)
            const response = await apiClient.get(API_ENDPOINTS.DATASETS, { params })
            return handleApiResponse<PaginatedResponse<Dataset>>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                'Failed to fetch datasets with pagination',
                'FETCH_DATASETS_PAGINATION_ERROR'
            )
        }
    },

    // 影像数据相关
    async getImageData(imageId: string): Promise<CustomImageData> {
        try {
            const response = await apiClient.get(API_ENDPOINTS.IMAGE_DATA(imageId), {
                responseType: 'arraybuffer' // 用于处理二进制数据
            })

            // 特殊处理：如果是二进制数据，需要转换格式
            if (response.headers['content-type']?.includes('application/octet-stream')) {
                return {
                    id: imageId,
                    pixelData: response.data,
                    // 其他属性需要从headers或单独的metadata请求获取
                } as CustomImageData
            }

            return handleApiResponse<CustomImageData>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                `Failed to fetch image data ${imageId}`,
                'FETCH_IMAGE_DATA_ERROR'
            )
        }
    },

    async getImageMetadata(imageId: string): Promise<ImageMetadata> {
        try {
            const response = await apiClient.get(API_ENDPOINTS.IMAGE_METADATA(imageId))
            return handleApiResponse<ImageMetadata>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                `Failed to fetch image metadata ${imageId}`,
                'FETCH_IMAGE_METADATA_ERROR'
            )
        }
    },

    async uploadImages(datasetId: string, files: File[]): Promise<CustomImageData[]> {
        try {
            const formData = new FormData()
            files.forEach((file, index) => {
                formData.append(`images[${index}]`, file)
            })

            const response = await apiClient.post(
                `${API_ENDPOINTS.DATASET(datasetId)}/images`,
                formData,
                {
                    headers: {
                        'Content-Type': 'multipart/form-data'
                    },
                    timeout: 120000 // 2分钟超时，用于大文件上传
                }
            )
            return handleApiResponse<CustomImageData[]>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                'Failed to upload images',
                'UPLOAD_IMAGES_ERROR'
            )
        }
    },

    async deleteImages(imageIds: string[]): Promise<void> {
        try {
            await apiClient.delete('/images', {
                data: { imageIds }
            })
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                'Failed to delete images',
                'DELETE_IMAGES_ERROR'
            )
        }
    },

    // 任务相关
    async getTasks(datasetId: string): Promise<Task[]> {
        try {
            const response = await apiClient.get(API_ENDPOINTS.TASKS(datasetId))
            return handleApiResponse<Task[]>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                `Failed to fetch tasks for dataset ${datasetId}`,
                'FETCH_TASKS_ERROR'
            )
        }
    },

    async createTask(data: CreateTaskRequest): Promise<Task> {
        try {
            const response = await apiClient.post('/tasks', data)
            return handleApiResponse<Task>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                'Failed to create task',
                'CREATE_TASK_ERROR'
            )
        }
    },

    async updateTask(id: string, data: UpdateTaskRequest): Promise<Task> {
        try {
            const response = await apiClient.put(`/tasks/${id}`, data)
            return handleApiResponse<Task>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                `Failed to update task ${id}`,
                'UPDATE_TASK_ERROR'
            )
        }
    },

    async deleteTask(id: string): Promise<void> {
        try {
            await apiClient.delete(`/tasks/${id}`)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                `Failed to delete task ${id}`,
                'DELETE_TASK_ERROR'
            )
        }
    },

    async startTask(taskId: string, params: TaskParams): Promise<TaskResult> {
        try {
            const response = await apiClient.post(API_ENDPOINTS.START_TASK, {
                taskId,
                params
            })
            return handleApiResponse<TaskResult>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                `Failed to start task ${taskId}`,
                'START_TASK_ERROR'
            )
        }
    },

    async cancelTask(id: string): Promise<void> {
        try {
            await apiClient.post(`/tasks/${id}/cancel`)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                `Failed to cancel task ${id}`,
                'CANCEL_TASK_ERROR'
            )
        }
    },

    async getTaskStatus(taskId: string): Promise<TaskStatusInfo> {
        try {
            const response = await apiClient.get(API_ENDPOINTS.TASK_STATUS(taskId))
            return handleApiResponse<TaskStatusInfo>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                `Failed to fetch task status ${taskId}`,
                'FETCH_TASK_STATUS_ERROR'
            )
        }
    },

    async getTaskResults(taskId: string): Promise<TaskResult[]> {
        try {
            const response = await apiClient.get(API_ENDPOINTS.TASK_RESULTS(taskId))
            return handleApiResponse<TaskResult[]>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                `Failed to fetch task results ${taskId}`,
                'FETCH_TASK_RESULTS_ERROR'
            )
        }
    },

    async getTasksWithPagination(datasetId: string, pagination?: PaginationOption): Promise<PaginatedResponse<Task>> {
        try {
            const params = buildQueryParams(pagination)
            const response = await apiClient.get(API_ENDPOINTS.TASKS(datasetId), { params })
            return handleApiResponse<PaginatedResponse<Task>>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                `Failed to fetch tasks with pagination for dataset ${datasetId}`,
                'FETCH_TASKS_PAGINATION_ERROR'
            )
        }
    },

    // 健康检查
    async healthCheck(): Promise<{ status: string; timestamp: string }> {
        try {
            const response = await apiClient.get('/health')
            return handleApiResponse<{ status: string; timestamp: string }>(response)
        } catch (error) {
            throw error instanceof ApiClientError ? error : new ApiClientError(
                'Health check failed',
                'HEALTH_CHECK_ERROR'
            )
        }
    }
}

// 导出API客户端实例
export default api

// 导出错误类
export { ApiClientError }